

package fr.jade.service.nodes.deployer;

import java.util.Map;

import org.objectweb.fractal.adl.implementations.ImplementationBuilder;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.control.BindingController;
import org.objectweb.fractal.api.control.IllegalBindingException;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.api.factory.GenericFactory;
import org.objectweb.fractal.api.factory.InstantiationException;
import org.objectweb.fractal.api.type.ComponentType;
import org.objectweb.fractal.util.Fractal;

import fr.jade.base.JadeBaseComponent;
import fr.jade.service.nodes.factory.NodeFactory;
import fr.jade.util.FractalUtil;

/**
 * This builder is used to deploy the nodes. Deploying a node means deploying 
 * a generic factory on a remote, physical node. Generic factory are deployed 
 * using a node factory.
 * @see fr.jade.service.nodes.NodeFactoryMixin
 * @author nono
 * @author Sylvain Sicard
 * @contact noel.depalma@inrialpes.fr
 */
public class NodesImplementationBuilder extends JadeBaseComponent implements  BindingController, ImplementationBuilder
{
	
	/**
	 * the node factory used to create the nodes.
	 */
	private NodeFactory nodefactory;
	
	public Object createComponent (
			final Object type, 
			final String name,
			final String definition,
			final Object controllerDesc, 
			final Object contentDesc, 
			final Object context) throws Exception
	{   
		Component res = null;
		String physicalNode = null;
		
		if (definition!=null && definition.equals("fr.jade.service.nodes.Node")) {
			if (context!=null)
				physicalNode = (String) (((Map)context).get("physicalNode"));
			if (physicalNode!=null) { // name is the virtual node
				res = nodefactory.newNode(physicalNode, name);
			} else { // name is the physical node
				res = nodefactory.newNode(name, null);
			}
		}else{// else create a std cmp (i.e. the root cluster)
		  res = createCMP(type,name,definition,controllerDesc,contentDesc,context);
		}
		return res;
	}
	
	/*
	 * Used to created root clusters & cluster
	 */
	private Component createCMP (
			final Object type, 
			final String name,
			final String definition,
			final Object controllerDesc, 
			final Object contentDesc, 
			final Object context) throws Exception 
	{
		Component bootstrap = null;
		bootstrap = (Component)((Map)context).get("bootstrap");
		
		log("Create CMP : " + name + " " + definition + " " + (String)contentDesc + " " + (String)controllerDesc);

		if (bootstrap == null) throw new InstantiationException("no bootstrap component in context");
		
		GenericFactory lf = Fractal.getGenericFactory(bootstrap);

		Component result = lf.newFcInstance( (ComponentType)type, controllerDesc, contentDesc);
		try {
			FractalUtil.getNameController(result).setFcName(name);
		} catch (NoSuchInterfaceException ignored) {}
		
		return result;
	}
	
	public String[] listFc ()
	{
		return new String[] { "nodefactory"};
	}
	
	public Object lookupFc (final String cItf) throws NoSuchInterfaceException
	{
		if (cItf.equals("nodefactory")) {
			return nodefactory;
		}
		return super.lookupFc(cItf);
	}
	
	public void bindFc (final String cItf, final Object sItf) throws NoSuchInterfaceException, IllegalBindingException, IllegalLifeCycleException
	{
		if (cItf.equals("nodefactory")) {
			nodefactory = (NodeFactory)sItf;
		} else 
		  super.bindFc(cItf, sItf);
	}
	
	public void unbindFc (final String cItf) throws NoSuchInterfaceException, IllegalBindingException, IllegalLifeCycleException
	{
		if (cItf.equals("nodefactory")) {
			nodefactory = null;
		} else  
		  super.unbindFc(cItf);
	}
	
}
